﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Net;
using System.IO;
using HtmlAgilityPack;

namespace WSI.SitesInteractor
{
    public class WebInteractor
    {
        #region Private members

        AppConfigurationHelper configHelper = new AppConfigurationHelper(ConfigurationManager.AppSettings["ConfigFilePath"]);
        private static CookieContainer cookies = new CookieContainer();
        private static string userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.1)";

        #endregion

        #region Authentication

        public bool Login(string httpMethod, params string[] loginArgs)
        {
            if (cookies.Count > 0)
                cookies = new CookieContainer();

            switch (httpMethod)
            {
                case "GET":
                    return LoginWithGET(loginArgs);

                case "POST":
                    return LoginWithPOST(loginArgs);

                default:
                    throw new NotSupportedException("HTTP method is not supported for login.");
            }
        }

        public void Logout()
        {
            cookies = new CookieContainer();
        }

        public bool IsLoggedIn
        {
            get
            {
                return cookies.Count > 0;
            }
        }

        #endregion

        #region Send request

        public string SendGETRequest(string address)
        {
            return SendGETRequest(address, null, null);
        }

        public string SendGETRequest(string address, string queryStringFormat, params string[] queryArgs)
        {
            if (!string.IsNullOrEmpty(queryStringFormat))
            {
                address = address + "?" + string.Format(queryStringFormat, queryArgs);
            }
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
            request.UserAgent = userAgent;
            request.CookieContainer = cookies;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader responseReader = new StreamReader(response.GetResponseStream());
            return responseReader.ReadToEnd();
        }

        public string SendPOSTRequest(string address, string postDataFormat, params string[] postArgs)
        {
            string requestUrl = address;

            ASCIIEncoding encoding = new ASCIIEncoding();
            string postData = string.Format(postDataFormat, postArgs);

            byte[] data = encoding.GetBytes(postData);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.UserAgent = userAgent;
            request.CookieContainer = cookies;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            Stream requestStream = request.GetRequestStream();
            requestStream.Write(data, 0, data.Length);
            requestStream.Close();

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader responseReader = new StreamReader(response.GetResponseStream());
            return responseReader.ReadToEnd();
        }

        #endregion

        #region Parse methods

        public string GetSingleValue(string pageSource, string xpathExpression)
        {
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(pageSource);

            HtmlNode node = doc.DocumentNode.SelectSingleNode(xpathExpression);

            return node.InnerText;
        }

        public List<string> GetValuesList(string pageSource, string xpathExpression)
        {
            List<string> valuesList = new List<string>();
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(pageSource);

            HtmlNodeCollection nodesList = doc.DocumentNode.SelectNodes(xpathExpression);
            foreach (var node in nodesList)
            {
                valuesList.Add(node.InnerText);
            }

            return valuesList;
        }
                
        public HtmlNodeCollection GetNodesList(string pageSource, string xpathExpression)
        {
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(pageSource);

            return doc.DocumentNode.SelectNodes(xpathExpression);
        }

        #endregion

        #region Private methods

        private bool LoginWithGET(string[] loginArgs)
        {
            string requestUrl = configHelper["loginUrl"] + "?" + string.Format(configHelper["loginDataFormat"], loginArgs);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
            request.UserAgent = userAgent;
            request.CookieContainer = cookies;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            return IsLoggedIn;
        }

        private bool LoginWithPOST(string[] loginArgs)
        {
            SendPOSTRequest(configHelper["loginUrl"], configHelper["loginDataFormat"], loginArgs);

            return IsLoggedIn;
        }

        #endregion
    }
}
